package cc.rengu.igas.share.core.service.trans;

import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.enums.FeeTypeEnum;
import cc.rengu.igas.share.common.enums.RespCodeEnum;
import cc.rengu.igas.share.core.model.MchntFeeInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.QrCodeInfo;
import cc.rengu.igas.share.core.realize.BompService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.BompServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.service.base.QueryService;
import cc.rengu.igas.share.facade.request.UpqcQrCodeQueryRequest;
import cc.rengu.igas.share.facade.response.UpqcQrCodeQueryResponse;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.TimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 银联二维码订单查询服务
 * * 查询订单 UP->AC
 * * reqType:0120000903
 * * 有银联向收单侧发起二维码交易查询
 */
public class UpqcQrCodeQueryService extends QueryService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        UpqcQrCodeQueryRequest upqcQrCodeQueryRequest = new UpqcQrCodeQueryRequest();
        ConvertUtil.convertOutput(upqcQrCodeQueryRequest);
        return upqcQrCodeQueryRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        xmlTreeUtil.setXmlTreeStringValue("invoiceSt", "N");
        UpqcQrCodeQueryRequest upqcQrCodeQueryRequest = (UpqcQrCodeQueryRequest) request;
        UpqcQrCodeQueryResponse qrCodeQueryResponse;
        String qrCode = URLDecoder.decode(upqcQrCodeQueryRequest.getQrCode(), "UTF-8");
        rglog.debug("银联二维码订单查询<{}>", qrCode);
        int lastIndex = qrCode.lastIndexOf("inf=");
        if (lastIndex < 0) {
            rglog.error("二维码<{}>格式错误", qrCode);
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
        String qrCodeType = qrCode.substring(lastIndex + 4, lastIndex + 5);
        if ("S".equals(qrCodeType)) {
            qrCodeQueryResponse = staticQrCodeQuery(upqcQrCodeQueryRequest);
        } else if ("D".equals(qrCodeType)) {
            qrCodeQueryResponse = dynamicQrCodeQuery(upqcQrCodeQueryRequest);
        } else {
            rglog.error("二维码<{}>格式错误", qrCode);
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }

        /*异步调用订单查证接口*/
        AsynNotify asynNotify = new AsynNotify();
        int iReturnCode = asynNotify.transactionNotice(ShareServiceConstant.ASYN_PAYORDERSTATUS_QUERY_SERVICE, 5, AsynNotify.GAP_SAME, 60 * 1000);
        if (iReturnCode != 0) {
            rglog.error("异步调起全渠道交易状态查询失败");
        }

        /* 组装应答报文 */
        BizResponse response = new BizResponse();
        response.setResult(qrCodeQueryResponse);
        response.setRspSysId(AppParamConstant.IGAS);
        response.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        response.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return response;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UpqcQrCodeQueryResponse qrCodeQueryResponse = (UpqcQrCodeQueryResponse) bizResponse.getResult();
        ConvertUtil.convertInput(qrCodeQueryResponse);
    }

    /* 静态码 */
    private UpqcQrCodeQueryResponse staticQrCodeQuery(UpqcQrCodeQueryRequest qrCodeQueryRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        UpqcQrCodeQueryResponse qrCodeQueryResponse = new UpqcQrCodeQueryResponse();
        /*增加C1码处理，去掉C1码中的&&tt部分*/
        String qrCodeUrl = filterTtAndSi(qrCodeQueryRequest.getQrCode());
        BompService bompService = new BompServiceImpl();
        QrCodeInfo qrCodeInfo = bompService.getQrCodeInfo(qrCodeQueryRequest.getHeader().getInstId(), qrCodeUrl, null);
        String currentTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        if (null == qrCodeInfo || !"00".equals(qrCodeInfo.getQrStatus())) {
            rglog.error("机构<{}>没有对应的银联二维码信息<{}>", qrCodeQueryRequest.getHeader().getInstId(), qrCodeQueryRequest.getQrCode());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        } else if ("00".equals(qrCodeInfo.getBindStatus())) {
            rglog.error("二维码未绑定!");
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        } else if (!StringUtil.isEmptyOrNull(qrCodeInfo.getEffectiveTime())
                && DateUtil.compareTime(currentTime, qrCodeInfo.getEffectiveTime(), "yyyy-MM-dd HH:mm:ss.SSS") < 0) {
            rglog.error("二维码未生效!");
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        } else if (!StringUtil.isEmptyOrNull(qrCodeInfo.getExpiryTime())
                && DateUtil.compareTime(currentTime, qrCodeInfo.getExpiryTime(), "yyyy-MM-dd HH:mm:ss.SSS") > 0) {
            rglog.error("二维码已失效!");
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
        String mchntNo = qrCodeInfo.getMchntNo();
        /*根据商户号获取商户信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(qrCodeQueryRequest.getHeader().getInstId(), mchntNo);
        if (null == mchntInfo) {
            rglog.error("查询商户基本信息失败<{}>", mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        /*增加商户业务权限校验 */
        boolean checkResult = mchntService.checkMchntAuth(qrCodeQueryRequest.getHeader().getInstId(), mchntNo, null,
                this.txnInfo.getSrcTxnAuthCfg().getTxnNum(), this.txnInfo.getSrcTxnAuthCfg().getBizType(), AcctTypeEnum.ALL.getAcctType());
        if (!checkResult) {
            rglog.error("商户<{}>无此交易权限!", mchntNo);
            throw new BizException(RespCodeEnum.TRANS_NOT_SUPPORT.getRespCode(), RespCodeEnum.TRANS_NOT_SUPPORT.getRespDesc());
        }
        /*商户限额处理,判断交易是否支持借记卡和贷记卡*/
        int limitFlag = mchntService.checkMchntTransLimit(qrCodeQueryRequest.getHeader().getInstId(), "0.00", LimitAcctTypeEnum.ALL, mchntNo, null, this.txnInfo.getSrcTxnAuthCfg().getTxnNum());
        if (0 != limitFlag) {
            if (1 == limitFlag) {
                /*银联扣款只允许借记卡支付*/
                rglog.debug("银联扣款只允许借记卡支付");
                /*10-一般消费；11-限定非贷记账户支付的消费*/
                qrCodeQueryResponse.setOrderType("11");
            } else {
                rglog.error("商户限额超限，不允许交易!");
                throw new BizException(RespCodeEnum.TRANS_LIMIT_OVERRUN.getRespCode(), RespCodeEnum.TRANS_LIMIT_OVERRUN.getRespDesc());
            }
        } else {
            String orderType = checkMchntSuportCredit(mchntNo, qrCodeQueryRequest.getHeader().getInstId());
            rglog.info("返回给银联二维码的订单类型:<{}>", orderType);
            qrCodeQueryResponse.setOrderType(orderType);
        }
        UserOrderInfo userOrderInfo = convUserOrderInfo(qrCodeQueryRequest, qrCodeInfo);
        List<MchntOrderInfo> mchntOrderInfoList = convMchntOrderInfo(qrCodeQueryRequest, qrCodeInfo, mchntInfo);
        PayOrderInfo payOrderInfo = convPayOrderInfo(userOrderInfo, qrCodeQueryRequest);
        payOrderInfo.setMchntNo(mchntNo);
        if (!orderService.registerOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }
        ConvertUtil.convertOutput(qrCodeQueryResponse);
        qrCodeQueryResponse.setOrderId(payOrderInfo.getChannelReconKey());
        qrCodeQueryResponse.setOrderTime(payOrderInfo.getTxnDate() + payOrderInfo.getTxnTime());
        qrCodeQueryResponse.setPaymentValidTime(String.valueOf(300));
        qrCodeQueryResponse.setAcqInsCode(mchntInfo.getCupsInstId());
        qrCodeQueryResponse.setAreaInfo("156" + mchntInfo.getCupsAreaCode());
        if (payOrderInfo.getOrderAmt() != null && !payOrderInfo.getOrderAmt().isEmpty()) {
            qrCodeQueryResponse.setOrderAmt(AmountUtil.changeY2F(payOrderInfo.getOrderAmt()));
        }
        qrCodeQueryResponse.setQrCodeType("1");//银联静态码值为1

        /*请求方保留域填写机构号*/
        JSONObject jsonObject = new JSONObject();
        /*扩展域中保存机构和商户号,收单机构号*/
        jsonObject.put("instId", qrCodeQueryRequest.getHeader().getInstId());
        jsonObject.put("mchntNo", mchntNo);
        if (!StringUtil.isEmptyOrNull(mchntInfo.getCupsInstId())) {
            jsonObject.put("acqInsCode", mchntInfo.getCupsInstId());
        }
        xmlTreeUtil.setXmlTreeStringValue("reqReserved", new String(Base64.encodeBase64(jsonObject.toJSONString().getBytes())));

        return qrCodeQueryResponse;
    }

    /* 动态码 */
    private UpqcQrCodeQueryResponse dynamicQrCodeQuery(UpqcQrCodeQueryRequest qrCodeQueryRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        long orderExpiryTime;
        UpqcQrCodeQueryResponse qrCodeQueryResponse = new UpqcQrCodeQueryResponse();
        /*根据二维码查询用户订单表*/
        UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
        UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByOrderUrl(qrCodeQueryRequest.getHeader().getInstId(), qrCodeQueryRequest.getQrCode());
        if (userOrderInfo == null) {
            rglog.error("机构<{}>没有对应的银联二维码信息<{}>", qrCodeQueryRequest.getHeader().getInstId(), qrCodeQueryRequest.getQrCode());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
        /*校验订单有效性*/
        checkUserOrderPayValidity(userOrderInfo);
        if (userOrderInfo.getOrderExpiryTime() == null || userOrderInfo.getOrderExpiryTime().isEmpty()) {
            orderExpiryTime = 300;
        } else {
            if (getTimeCost(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"), userOrderInfo.getOrderExpiryTime()) > 300) {
                orderExpiryTime = 300;
            } else {
                orderExpiryTime = getTimeCost(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"), userOrderInfo.getOrderExpiryTime());
            }
        }

        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());
        if (mchntOrderInfoList.size() > 1 &&
                !"00".equals(mchntOrderInfoList.get(0).getBizStatus()) &&
                !"02".equals(mchntOrderInfoList.get(0).getBizStatus())) {
            rglog.error("二维码信息<{}>聚合支付只支持单商户支付", qrCodeQueryRequest.getQrCode());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
        MchntOrderInfo mchntOrderInfo = mchntOrderInfoList.get(0);
        String mchntNo = mchntOrderInfo.getMchntNo();

        /*根据商户号获取商户信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(qrCodeQueryRequest.getHeader().getInstId(), mchntNo);
        if (null == mchntInfo) {
            rglog.error("查询商户基本信息失败<{}>", mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        /*查询银联商户，获取对应的收单机构号*/
        boolean checkResult = mchntService.checkMchntAuth(qrCodeQueryRequest.getHeader().getInstId(), mchntNo, null,
                this.txnInfo.getSrcTxnAuthCfg().getTxnNum(), this.txnInfo.getSrcTxnAuthCfg().getBizType(), AcctTypeEnum.ALL.getAcctType());
        if (!checkResult) {
            rglog.error("商户<{}>无此交易权限!", mchntNo);
            throw new BizException(RespCodeEnum.TRANS_NOT_SUPPORT.getRespCode(), RespCodeEnum.TRANS_NOT_SUPPORT.getRespDesc());
        }
        /*商户限额处理,判断交易是否支持借记卡和贷记卡*/
        int limitFlag = mchntService.checkMchntTransLimit(qrCodeQueryRequest.getHeader().getInstId(), "0.00", LimitAcctTypeEnum.ALL, mchntNo, null, this.txnInfo.getSrcTxnAuthCfg().getTxnNum());
        if (0 != limitFlag) {
            if (1 == limitFlag) {
                /*银联扣款只允许借记卡支付*/
                rglog.debug("银联扣款只允许借记卡支付");
                /*10-一般消费；11-限定非贷记账户支付的消费*/
                qrCodeQueryResponse.setOrderType("11");
            } else {
                rglog.error("商户限额超限，不允许交易!");
                throw new BizException(RespCodeEnum.TRANS_LIMIT_OVERRUN.getRespCode(), RespCodeEnum.TRANS_LIMIT_OVERRUN.getRespDesc());
            }
        } else {
            String orderType = checkMchntSuportCredit(mchntNo, qrCodeQueryRequest.getHeader().getInstId());
            rglog.info("返回给银联二维码的订单类型:<{}>", orderType);
            qrCodeQueryResponse.setOrderType(orderType);
        }
        for (MchntOrderInfo mchntOrderInfoUpqc : mchntOrderInfoList) {
            mchntOrderInfoUpqc.setTxnNum(qrCodeQueryRequest.getHeader().getTxnNum());
            mchntOrderInfoUpqc.setBizType(qrCodeQueryRequest.getHeader().getBizType());
            mchntOrderInfoUpqc.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            mchntOrderInfoUpqc.setTxnDate(DateUtil.getCurrentDate());
            mchntOrderInfoUpqc.setTxnTime(DateUtil.getCurrentTime());
            mchntOrderInfoUpqc.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfoUpqc.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            mchntOrderInfoUpqc.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            mchntOrderInfoUpqc.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        }

        /*更新用户订单表*/
        userOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        PayOrderInfo payOrderInfo = convPayOrderInfo(userOrderInfo, qrCodeQueryRequest);
        payOrderInfo.setMchntNo(mchntNo);
        if (!updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
            rglog.error("更新订单信息失败");
            throw new BizException(RespCodeEnum.ORDER_UPDATE_ERROR.getRespCode(), RespCodeEnum.ORDER_UPDATE_ERROR.getRespDesc());
        }
        ConvertUtil.convertOutput(qrCodeQueryResponse);
        qrCodeQueryResponse.setOrderId(payOrderInfo.getChannelReconKey());
        qrCodeQueryResponse.setOrderTime(payOrderInfo.getTxnDate() + payOrderInfo.getTxnTime());
        qrCodeQueryResponse.setPaymentValidTime(String.valueOf(orderExpiryTime));
        qrCodeQueryResponse.setAcqInsCode(mchntInfo.getCupsInstId());
        qrCodeQueryResponse.setAreaInfo("156" + mchntInfo.getCupsAreaCode());
        if (payOrderInfo.getOrderAmt() != null && !payOrderInfo.getOrderAmt().isEmpty()) {
            qrCodeQueryResponse.setOrderAmt(AmountUtil.changeY2F(payOrderInfo.getOrderAmt()));
        }
        qrCodeQueryResponse.setQrCodeType("0");//动态码

        /*请求方保留域填写机构号*/
        JSONObject jsonObject = new JSONObject();
        /*扩展域中保存机构和商户号,收单机构号*/
        jsonObject.put("instId", qrCodeQueryRequest.getHeader().getInstId());
        jsonObject.put("mchntNo", mchntNo);
        if (!StringUtil.isEmptyOrNull(mchntInfo.getCupsInstId())) {
            jsonObject.put("acqInsCode", mchntInfo.getCupsInstId());
        }
        xmlTreeUtil.setXmlTreeStringValue("reqReserved", new String(Base64.encodeBase64(jsonObject.toJSONString().getBytes())));

        return qrCodeQueryResponse;
    }


    private UserOrderInfo convUserOrderInfo(UpqcQrCodeQueryRequest request, QrCodeInfo qrCodeInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UserOrderInfo userOrderInfo = new UserOrderInfo();
        BeanUtil.beanCopy(request.getHeader(), userOrderInfo);
        userOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        userOrderInfo.setTxnDate(request.getHeader().getTransDate());
        userOrderInfo.setTxnTime(request.getHeader().getTransTime());
        userOrderInfo.setMsgSrcId(request.getHeader().getSrcSysId());
        userOrderInfo.setTransChannelId(request.getHeader().getChanlId());
        userOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        userOrderInfo.setOrderCcy("CNY");
        if (qrCodeInfo.getTransAmt() != null) {
            userOrderInfo.setOrderAmt(qrCodeInfo.getTransAmt());
            userOrderInfo.setNeedPayAmt(qrCodeInfo.getTransAmt());
        } else {
            userOrderInfo.setOrderAmt("0.00");
            userOrderInfo.setNeedPayAmt("0.00");
        }
        userOrderInfo.setFrontSeqNum(request.getHeader().getTraceNo());
        userOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        String orderCreateTime = DateUtil.getCurrentDateTime("yyyyMMddHHmmss");
        userOrderInfo.setOrderCreateTime(orderCreateTime);
        userOrderInfo.setOrderExpiryTime(TimeUtil.calcDays(orderCreateTime, Long.valueOf(300)));
        userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        // 静态码  银联返回的静态码值为1，数据库结果静态码值为0
        Map<String, String> orderExtraInfo = new HashMap<>();
        orderExtraInfo.put("qrCodeType", "0");
        userOrderInfo.setOrderExtraInfo(JSON.toJSONString(orderExtraInfo));
        userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        return userOrderInfo;
    }

    /**
     * 根据订单明细创建商户订单
     *
     * @return 商户订单
     * @throws Exception 异常
     */
    private List<MchntOrderInfo> convMchntOrderInfo(UpqcQrCodeQueryRequest request, QrCodeInfo qrCodeInfo, MchntInfo mchntInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<MchntOrderInfo> mchntOrderList = new ArrayList<>();
        String orderAmt = "0.00";
        if (qrCodeInfo.getTransAmt() != null) {
            orderAmt = qrCodeInfo.getTransAmt();
        }
        MchntOrderInfo mchntOrderInfo = new MchntOrderInfo();
        BeanUtil.beanCopy(request.getHeader(), mchntOrderInfo);
        mchntOrderInfo.setUserId(qrCodeInfo.getUserId());
        mchntOrderInfo.setTxnDate(request.getHeader().getTransDate());
        mchntOrderInfo.setTxnTime(request.getHeader().getTransTime());
        mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        mchntOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        mchntOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        mchntOrderInfo.setOrderDesc("");
        //商户签约机构
        mchntOrderInfo.setAcqInstCode(mchntInfo.getSignInstId());
        mchntOrderInfo.setIndustryType(mchntInfo.getIndustryType());
        mchntOrderInfo.setMchntNo(mchntInfo.getMchntNo());
        mchntOrderInfo.setMchntName(mchntInfo.getMchntName());
        mchntOrderInfo.setOrderCcy("CNY");
        mchntOrderInfo.setOrderAmt(orderAmt);
        mchntOrderInfo.setCustomerMarketAmt("0.00");
        mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        mchntOrderInfo.setRealSettleAmt(orderAmt);
        mchntOrderInfo.setRealSettleFlag("N");
        mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        // 静态码  银联返回的静态码值为1，数据库静态码值为0
        Map<String, String> orderExtraInfo = new HashMap<>();
        orderExtraInfo.put("qrCodeType", "0");
        mchntOrderInfo.setOrderExtraInfo(JSON.toJSONString(orderExtraInfo));
        mchntOrderList.add(mchntOrderInfo);

        return mchntOrderList;
    }

    private PayOrderInfo convPayOrderInfo(UserOrderInfo userOrderInfo, UpqcQrCodeQueryRequest request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        if (payOrderInfo.getOrderAmt() == null || payOrderInfo.getOrderAmt().isEmpty()) {
            payOrderInfo.setOrderAmt("0.00");
        }
        payOrderInfo.setMsgDstId(ChannelEnum.UPQC.getChannelType());
        payOrderInfo.setDstCallIndex("0");
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setDstTxnNum("");
        payOrderInfo.setOrderCcy("156");
        payOrderInfo.setPayType(PayTypeEnum.CUPS_CLOUD.getPayType());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        payOrderInfo.setBizType(request.getHeader().getBizType());
        return payOrderInfo;
    }

    void checkUserOrderPayValidity(UserOrderInfo userOrderInfo) throws Exception {
        if (OrderStatusEnum.CLOSE.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.info("用户订单已关闭.orderStatus:<{}>", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        } else if (OrderStatusEnum.FINISH.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.info("用户订单已完成.orderStatus:<{}>", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        } else if (BizStatusEnum.PROCESSING.getStatus().equals(userOrderInfo.getBizStatus())) {
            rglog.info("用户订单处理处理中，不允许再次发起支付。bizStatus:<{}>", userOrderInfo.getBizStatus());
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
        /*判断订单是否超过有效期*/
        if (DateUtil.compareTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"),
                userOrderInfo.getOrderExpiryTime(), "yyyyMMddHHmmss") > 0) {
            rglog.info("订单已经过了有效期，当前日期curDateTime:<{}>,订单有效期orderExpiryTime:<{}>",
                    DateUtil.getCurrentDateTime("yyyyMMddHHmmss"), userOrderInfo.getOrderExpiryTime());
            /*订单已失效更新订单已失效*/
            OrderService orderService = new OrderServiceImpl();
            userOrderInfo.setOrderStatus(OrderStatusEnum.INVALID.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
                rglog.error("更新用户订单/商户订单信息失败");
            }
            throw new BizException(RespCodeEnum.INVALID_QR_CODE.getRespCode(), RespCodeEnum.INVALID_QR_CODE.getRespDesc());
        }
    }

    private boolean updateOrderInfo(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {
        int iReturnCode;
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppParamConstant.DATABASE_CONF_NODE, AppParamConstant.OLTP_POOL_NAME);
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /* Step1：开启数据库事务 */
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppParamConstant.OLTP_POOL_NAME);
            dbsUtil = new DbsUtil(dbPoolName);
        }
        dbsUtil.dbsBeginTransaction();
        /* Step2：更新用户订单信息 */
        if (null != userOrderInfo) {
            UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
            iReturnCode = userOrderInfoMapper.updateUserOrderInfoByUserOrderId(userOrderInfo);
            if (0 != iReturnCode) {
                dbsUtil.dbsEndTransaction(false);
                return false;
            }
        }
        /* Step3：登记商户订单信息 */
        if (null != mchntOrderInfoList && !mchntOrderInfoList.isEmpty()) {
            MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                iReturnCode = mchntOrderInfoMapper.insertMchntOrderInfo(mchntOrderInfo);
                if (0 != iReturnCode) {
                    dbsUtil.dbsEndTransaction(false);
                    return false;
                }
            }
        }
        /* Step4：登记支付订单信息 */
        if (null != payOrderInfo) {
            PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
            iReturnCode = payOrderInfoMapper.insertPayOrderInfo(payOrderInfo);
            if (0 != iReturnCode) {
                dbsUtil.dbsEndTransaction(false);
                rglog.error("更新支付订单信息失败,sysSeqNum:<{}>,mchntOrderId:<{}>,channelId:<{}>,realPayAmt:<{}>,channelFee:<{}>,settleDate:<{}>,channelSeqNum:<{}>,iReturnCode:<{}>",
                        payOrderInfo.getSysSeqNum(), payOrderInfo.getMchntOrderId(), payOrderInfo.getMsgDstId(), payOrderInfo.getRealPayAmt(), payOrderInfo.getChannelFee(), payOrderInfo.getSettleDate(), payOrderInfo.getChannelSeqNum(), iReturnCode);
                return false;
            }
        }
        /* Step5：结束数据库事务 */
        dbsUtil.dbsEndTransaction(true);
        return true;
    }

    long getTimeCost(String startTime, String endTime) {
        SimpleDateFormat dfs = new SimpleDateFormat("yyyyMMddHHmmss");
        long between;
        try {
            Date begin = dfs.parse(startTime);
            Date end = dfs.parse(endTime);
            between = (end.getTime() - begin.getTime()) / 1000;// 得到两者的秒数
        } catch (Exception ex) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ex.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            return 0;
        }
        return between;
    }

    /**
     * 判断返回给银联的orderType
     *
     * @param mchntNo 商户号
     * @param instId  法人机构号
     * @return orderType
     */
    private String checkMchntSuportCredit(String mchntNo, String instId) throws Exception {
        //判断是否支持贷记卡
        boolean isSupportCredit = false;
        MchntService mchntService = new MchntServiceImpl();
        List<MchntFeeInfo> mchntFeeInfoList = mchntService.getMchntFeeInfo(instId, mchntNo);
        if (mchntFeeInfoList != null && !mchntFeeInfoList.isEmpty()) {
            mchntFeeInfoList = mchntFeeInfoList.stream().filter(item -> FeeTypeEnum.UPQR_CR.getFeeType().equals(item.getFeeType())
                    && BaseProdEnum.SCAN_CODE.getProdCode().equals(item.getBaseProdCode())
                    && item.getFeeEffectiveDate().compareTo(DateUtil.getCurrentDate()) <= 0
                    && item.getFeeExpiryDate().compareTo(DateUtil.getCurrentDate()) >= 0).collect(Collectors.toList());
            if (!mchntFeeInfoList.isEmpty()) {
                rglog.info("当前商户配置银联二维码贷记的费率数据，因此支持银联二维码贷记交易");
                isSupportCredit = true;
            }
        } else {
            rglog.error("当前商户:<{}>未配置商户费率信息,商户或机构状态不正确", mchntNo);
            throw new BizException(RespCodeEnum.NOT_SUPPORT_BIZ.getRespCode(), RespCodeEnum.NOT_SUPPORT_BIZ.getRespDesc());
        }

        //判断返回的orderType类型
        /*10-一般消费；11-限定非贷记账户支付的消费*/
        if (isSupportCredit) {
            return "10";
        } else {
            return "11";
        }
    }

    /**
     * 过滤C1码原串中的tt和si信息
     *
     * @param qrUrl 二维码信息
     * @return 处理后的二维码
     */
    private String filterTtAndSi(String qrUrl) throws Exception {
        if (qrUrl.indexOf("&si=") > 0) {
            StringBuilder sb = new StringBuilder();
            String paramterData;
            if (qrUrl.indexOf("?") > 0) {
                paramterData = qrUrl.substring(qrUrl.indexOf("?") + 1);
                sb.append(qrUrl, 0, qrUrl.indexOf("?") + 1);
            } else {
                paramterData = qrUrl.substring(qrUrl.lastIndexOf("/") + 1);
                sb.append(qrUrl, 0, qrUrl.lastIndexOf("/") + 1);
            }
            paramterData = URLDecoder.decode(paramterData, "UTF-8");
            //C1码
            String[] tempArray = paramterData.split("&");
            for (String item : tempArray) {
                if (!item.contains("tt=")
                        && !item.contains("si=")) {
                    sb.append(item);
                    sb.append("&");
                }
            }
            return sb.substring(0, sb.length() - 1);
        }
        return qrUrl;
    }
}
